<?php

class ShopService extends AbstractService
{
    /**
     * @var ShopService
     */
    private static $instance;

    /**
     * Get instance of ShopService.
     *
     * @return ShopService
     */
    public static function get()
    {
        if (!self::$instance) {
            self::$instance = new ShopService();
        }

        return self::$instance;
    }

    /**
     * Construction.
     */
    protected function __construct()
    {
        parent::__construct();
    }

    /**
     * 处理创建时的逻辑
     *
     * @param int $userId
     * @return void
     */
    public function handleCreate($userId)
    {
    }

    /**
     * 处理登录时的逻辑
     *
     * @param int $userId
     * @return void
     */
    public function handleLogin($userId)
    {

    }

    /**
     * 提供当前 service 数据
     *
     * @param int $userId
     * @param boolean $visitMode default false
     * @return array(RandomShopVoList)
     */
    public function info($userId, $visitMode = false)
    {
        $randomShopList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_RANDOM_SHOP);
        return array(
            $randomShopList
        );
    }

    /**
     * 重置随机商会的计数
     *
     * @param int $userId 用户ID
     * @return RandomShopVo
     */
    public function resetCocRandomShopCount($userId)
    {
        $randomShop = $this->resetRandomShopCount($userId, GameConst::RANDOM_SHOP_COC);

        // 数据采集:公会商店刷新
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:Guild|action:shop_refresh|',
                'value' => 1
            )
        ));

        return $randomShop;
    }

    /**
     * 重置机器人随机商店的计数
     *
     * @param int $userId 用户ID
     * @return RandomShopVo
     */
    public function resetRobotRandomShopCount($userId)
    {
        $randomShop = $this->resetRandomShopCount($userId, GameConst::RANDOM_SHOP_ROBOT);

        // 数据采集:公会商店刷新
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:vivian|action:shop_refresh|',
                'value' => 1
            )
        ));

        return $randomShop;
    }

    /**
     * 重置随机商店的计数
     *
     * @param int $userId 用户ID
     * @param int $shopType 商店类型 GameConst::RANDOM_SHOP_COC
     * @return RandomShopVo
     */
    private function resetRandomShopCount($userId, $shopType)
    {
        // 扣除消耗
        $luckyShopSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_ITEM_LUCKY_SHOP, $shopType, true);
        GameService::get()->handleEntity($userId, GameConst::ENTITY_ACTION_CONSUME_MONEY, $luckyShopSetting['cost'], true);

        // 重新随机出商店物品
        $randomShop = $this->refreshRandomShop($userId, $shopType, true);

        // 数据采集:公会商店刷新消耗钻石
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USE_GOLD, array(
            'clientData' => array(
                'item' => ($shopType == GameConst::RANDOM_SHOP_ROBOT) ? 'vivian_shop_refresh' :'Guild_shop_refresh',
                'value' => abs($luckyShopSetting['cost'])
            )
        ));

        return $randomShop;
    }

    /**
     * 购买随机商会的物品
     *
     * @param int $userId 用户ID
     * @param int $goodsId 配置表中的货物ID
     * @return int
     */
    public function buyCocRandomShopItem($userId, $goodsId)
    {
        $status = $this->buyRandomShopItem($userId, GameConst::RANDOM_SHOP_COC, $goodsId);

        if ($status == 1) {
            // 数据采集:公会商店购买
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
                'clientData' => array(
                    'tid' => 'Module:Guild|action:shop_buy|',
                    'item' => $goodsId,
                    'value' => 1
                )
            ));
        }

        return $status;
    }

    /**
     * 购买机器人随机商店的物品
     *
     * @param int $userId 用户ID
     * @param int $goodsId 配置表中的货物ID
     * @return int
     */
    public function buyRobotRandomShopItem($userId, $goodsId)
    {
        $status = $this->buyRandomShopItem($userId, GameConst::RANDOM_SHOP_ROBOT, $goodsId);

        if ($status == 1) {
            // 数据采集:好友随机商店
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
                'clientData' => array(
                    'tid' => 'Module:vivian|action:shop_buy|',
                    'item' => $goodsId,
                    'value' => 1
                )
            ));
        }

        return $status;
    }

    /**
     * 购买随机商店的道具
     *
     * @param int $userId 用户ID
     * @param int $shopType 商店类型 GameConst::RANDOM_SHOP_COC
     * @param int $goodsId 配置表中的货物ID
     * @return int
     */
    private function buyRandomShopItem($userId, $shopType, $goodsId)
    {
        /**
         * @var RandomShopVoList $randomShopList
         * @var RandomShopVo $randomShop
         */
        $randomShopList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_RANDOM_SHOP);
        $randomShop = $randomShopList->getElement($shopType, false);

        if (!$randomShop) {
            return 2;
        }

        // 判断 goodsId 是否合法
        $goodsOnSellList = $randomShop->getRawItemIdList();
        if (!SzUtility::checkArrayKey($goodsId, $goodsOnSellList) || $goodsOnSellList[$goodsId] != 0) {
            return 2;
        }

        // 商品配置不存在
        $goodsSettings = $this->loadGoodsConfig($shopType);
        if (!SzUtility::checkArrayKey($goodsId, $goodsSettings)) {
            return 3;
        }
        $goodsSetting = $goodsSettings[$goodsId];

        // 扣除购买消耗
        GameService::get()->handleEntity($userId, $goodsSetting['moneyType'], $goodsSetting['cost'], true);
        CommonFunctionService::get()->reportResourceUseDetails(GameConst::FUNC_TRANSACTION_FUNC,$userId,0,$goodsSetting['moneyType'].':'.$goodsSetting['cost'].'|','buyRandomShopItem');//消耗资源上报

        // 更新已购买信息
        $goodsOnSellList[$goodsId] = 1;
        $randomShop->setItemIdList($goodsOnSellList);
        $randomShopList->updateElement($shopType, $randomShop);
        SzPersister::get()->setVoList($randomShopList);

        // 获得购买的道具
        GameService::get()->handleEntity($userId, $goodsSetting['itemId'], $goodsSetting['count'], true, false);
        CommonFunctionService::get()->reportResourceUseDetails(GameConst::FUNC_TRANSACTION_FUNC,$userId,1,$goodsSetting['itemId'].':'.$goodsSetting['count'].'|','buyRandomShopItem');//获得资源上报

        if (GameConst::CONFIG_ITEM_COC_GOODS == $shopType) {
            // 数据采集:公会商店购买消耗
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_INPUT, array(
                'clientData' => array(
                    'tid' =>  $goodsSetting['moneyType'] . ':' . $goodsSetting['cost'] . '|',
                    'item' => 'Guild_shop_buy'
                )
            ));

            // 数据采集:公会商店购买产出
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_OUTPUT, array(
                'clientData' => array(
                    'tid' =>  $goodsSetting['itemId'] . ':' . $goodsSetting['count'] . '|',
                    'item' => 'Guild_shop_buy'
                )
            ));
        } else {
            // 数据采集:好友随机商店购买消耗
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_INPUT, array(
                'clientData' => array(
                    'tid' =>  $goodsSetting['moneyType'] . ':' . $goodsSetting['cost'] . '|',
                    'item' => 'vivian_shop_buy'
                )
            ));

            // 数据采集:好友随机商店购买产出
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_OUTPUT, array(
                'clientData' => array(
                    'tid' =>  $goodsSetting['itemId'] . ':' . $goodsSetting['count'] . '|',
                    'item' => 'vivian_shop_buy'
                )
            ));
        }

        return GameConst::COC_RETURN_ID_SUCCESS;
    }

    /**
     * 更新随机商店的信息
     *
     * @param int $userId 用户ID
     * @param int $shopType 商店类型 GameConst::RANDOM_SHOP_COC
     * @param bool $forcedRefresh 强制刷新
     * @return RandomShopVo
     */
    public function refreshRandomShop($userId, $shopType, $forcedRefresh = false)
    {
        $reqTime = GameService::get()->getReqTime();
        $luckyShopSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_ITEM_LUCKY_SHOP, GameConst::RANDOM_SHOP_COC, true);

        /**
         * @var RandomShopVoList $randomShopList
         * @var RandomShopVo $randomShop
         */
        $randomShopList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_RANDOM_SHOP);
        $randomShop = $randomShopList->getElement($shopType, false);

        if (!$randomShop) {
            $randomShop = new RandomShopVo(
                $userId, // userId
                $shopType, // typeId
                GameConst::DEFAULT_JSON_STRING, // itemIdList
                0, // lastTime
                true
            );
        }

        if ($reqTime > $randomShop->getLastTime() + $luckyShopSetting['intervalValue'] || $forcedRefresh) {
            $_itemIdList = $this->randomShopGoodsList($userId, $shopType, $luckyShopSetting['shelfCount']);
            $randomShop->setItemIdList($_itemIdList);
            $randomShop->setLastTime($reqTime - (($reqTime - $randomShop->getLastTime()) % $luckyShopSetting['intervalValue']));

            if ($randomShop->isInsert() && !SzUtility::checkArrayKey($shopType, $randomShopList->getList())) {
                $randomShopList->addElement($randomShop);
                $randomShopList->setElement($shopType, $randomShop);
            } else {
                $randomShopList->updateElement($shopType, $randomShop);
            }

            SzPersister::get()->setVoList($randomShopList);
        }

        return $randomShop;
    }

    /**
     * 获取随机商店的物品列表信息
     *
     * @param int $userId 用户ID
     * @param int $shopType 商店类型 GameConst::RANDOM_SHOP_COC
     * @param int $shelfCount 显示列表的数量
     * @return array 返回有效的显示列表ID
     * <pre>
     * array(
     *  $itemDefId => $isBought
     * )
     * </pre>
     */
    private function randomShopGoodsList($userId, $shopType, $shelfCount)
    {
        $goodsSettings = $this->loadGoodsConfig($shopType);

        // 过滤出符合条件的商品
        $userLevel = UserService::get()->getUserLevel($userId);
        $probabilityList = array();
        foreach ($goodsSettings as $goodsId => $goodsSetting) {
            if ($goodsSetting['luckyShopId'] != $shopType || $goodsSetting['level'] > $userLevel) {
                continue;
            }
            list(, , $itemDefId) = EntityService::get()->parseEntityId($goodsSetting['itemId']);
            if (!CollectionService::get()->isUnlock($userId, $itemDefId)) {
                continue;
            }
            $probabilityList[$goodsId] = $goodsSetting['weight'];
        }

        $goodsList = array();
        while ($shelfCount) {
            if (count($probabilityList) == 0) {
                break;
            }
            $goodsId = GameService::get()->getRandomElementByProbability($probabilityList);
            $goodsList[$goodsId] = 0;
            unset($probabilityList[$goodsId]);
            $shelfCount--;
        }

        return $goodsList;
    }

    /**
     * 获取不同店铺商品配置
     *
     * @param int $shopType 商店类型 GameConst::RANDOM_SHOP_COC
     * @param string $key default null, means load whole file
     * @return array
     */
    private function loadGoodsConfig($shopType, $key = null)
    {
        switch ($shopType) {
            case GameConst::RANDOM_SHOP_COC:
                return SzConfig::get()->loadAppConfig(GameConst::CONFIG_ITEM_COC_GOODS, $key, true, false);
            case GameConst::RANDOM_SHOP_ROBOT:
                return SzConfig::get()->loadAppConfig(GameConst::CONFIG_ITEM_LUCKY_GOODS, $key, true, false);
            default:
                return null;
        }
    }
}